<?php

/*

$this->form('user-registration','Registration')
	->text('name','Name')
	->select('role','Role',array(
		'TEACHER' => 'Teacher',
		'PARENT' => 'Parent',
		'STUDENT' => 'Student'))
	->button('add-user','Submit')
	->render();

validation / model / parameters

$form->bind(object);

$form->validate();

FONTOS: a doksiba... van egy 'filed' nevu mezo is a widegtekhez
van egy rejtetee _f_value_loader_ mezo is
	
*/

class _F_EXTENSION_FORM_OBJECT_ extends _F_OBJECT_ {
	
	public $form;
	public $id;
	public $method = 'POST'; // GET | POST | AJAX
	public $action = null;
	public $title = null;
	public $elements = array();
	public $attr = array();	
	public $messages = array();	
	
	public $default_properties = array(
		'wrapper' => 'form.wrapper',
		'attr' => array(),
		'size' => 'auto',
		'disabled' => false,
		'class' => '',
		'trim' => false,
	);
	
	public function __construct($id,$title = null,$options = null) {
		$this->form = $this;
		if (isset($title)) {
			if (is_array($title)) $options = $title;
			else $this->title = $title;
		}
		$this->id = $id;
		$this->put_properties($options);
	}
	
	public function hidden($id,$value) {
		$this->elements[$id] = array('id' => $id,
			'value' => $value, 'wrapper' => 'form.hidden');
		return $this;
	}

	public function text($id,$label,$params = array()) {
		$element = array_merge($this->default_properties,array(
			'template' => 'form.text',
			'rows' => 1,
			'size' => 'medium',
		),$params,array('id' => $id, 'widget' => 'text','label' => $label));
		if ($element['rows'] > 1) {
			$element['size'] = 'large';
			$element['attr']['rows'] = $element['rows'];
		}
		$this->elements[$id] = $element;		
		return $this;
	}
 	
	public function password($id,$label,$params = array()) {
		$this->elements[$id] = array_merge($this->default_properties,array(
			'template' => 'form.password',
			'size' => 'small',
		),$params,array('id' => $id, 'widget' => 'password','label' => $label));
		return $this;
	}
 	
	public function select($id,$label,$options,$params = array()) {
		$this->elements[$id] = array_merge($this->default_properties,array(
			'template' => 'form.select',
		),$params,array('id' => $id, 'widget' => 'select',
			'label' => $label, 'options' => $options));
		return $this;
	}

	public function radio($id,$label,$options,$params = array()) {
		$this->elements[$id] = array_merge($this->default_properties,array(
			'template' => 'form.radio',
		),$params,array('id' => $id, 'widget' => 'radio',
			'label' => $label, 'options' => $options));
		return $this;
	}

	public function checkbox($id,$label,$params = array()) {
		$this->elements[$id] = array_merge($this->default_properties,array(			
			'template' => 'form.checkbox',
			'_f_value_loader_' => array('_F_EXTENSION_FORM_OBJECT_',
				'_f_checkbox_value_loader_'),
//			'_f_value_saver_' =>
			'value' => false,
		),$params,array('id' => $id, 'widget' => 'checkbox',
			'label' => $label));
		return $this;
	}
	
	public static function _f_checkbox_value_loader_($form,$id,&$element,$model) {
		$value = f()->param($id);
		if ($value === null && isset($model)) {
			$name = isset($element['field']) ? $element['field'] : $id;
			if (is_array($model) && isset($model[$name])) {
			 	$value = $model[$name];
			} else if (is_object($model) && isset($model->$name)) {
				$value = $model->$name;
			}
		}
		if ((is_string($value) && (strtolower($value) == 't' 
				|| strtolower($value) == 'true' 
				|| strtolower($value) == 'on' 
				|| strtolower($value) == 'yes'
				|| strtolower($value) == '1'))
				|| (is_numeric($value) && $value != 0) 
				|| (is_bool($value) && $value)) {
			$element['value'] = true;
		} else {
			$element['value'] = false;
		}
	}

	public function button($id,$label,$action = 'submit',$params = array()) {
		$this->elements[$id] = array_merge($this->default_properties + array(
			'template' => 'form.button',
		),$params,array('id' => $id, 'widget' => 'button', 
			'label' => $label, 'action' => $action));
		return $this;
	}

	public function group($id,$label) {
		$group = new _F_EXTENSION_FORM_OBJECT_($this->id);
		$group->form = $this;
		f()->form()->put_registered_widgets($group);
		$this->elements[$id] = array_merge($this->default_properties + array(
			'_f_is_container_' => true,
			'template' => 'form.group', 
			'id' => $id, 
			'widget' => 'group', 
			'label' => $label, 
			'elements' => $group,
		));
		return $group;
	}
	
	public function load($model = null, $fields = null) {
		$this->_f_load_($this,$this,$model,$fields);
		return $this;
	}
	
	public static function _f_load_($form,$parent,$model,$fields) {
		foreach ($parent->elements as $id => &$element) {
			if (isset($element['_f_is_container_']) && $element['_f_is_container_']) {
				_F_EXTENSION_FORM_OBJECT_::_f_load_($form,
					$element['elements'],$model,$fields);
			} else {
				if ($fields === null || in_array($id,$fields)) {
					if (isset($element['_f_value_loader_'])) {
						call_user_func($element['_f_value_loader_'],
							$form,$id,&$element,$model);
					} else {
						if (isset($model)) {
							$name = isset($element['field']) ? $element['field'] : $id;
							if (is_array($model) && isset($model[$name])) {
							 	$element['value'] = $model[$name];
							} else if (is_object($model) && isset($model->$name)) {
								$element['value'] = $model->$name;
							}
						}
						$value = f()->param($id);
						if ($element['trim']) $value = trim($value);
						if (!$element['disabled'] && $value !== null) 
							$element['value'] = $value;
					}
				}
			}
		}
	}

	public function validate() {
		return $this->_f_validate_($this,$this,$this->messages,true);
	}
	
	public static function _f_validate_($form,$parent,&$messages,$good) {
		$form_extension = f()->form();
		$validators = $form_extension->validators;
		foreach ($parent->elements as $id => &$element) {
			if (isset($element['_f_is_container_']) && $element['_f_is_container_']) {
				$good = _F_EXTENSION_FORM_OBJECT_::_f_validate_($form,
					$element['elements'],&$messages,$good);
			} else if (isset($element['validate'])) {				
				foreach ($element['validate'] as $validator) {
					$fn = $validator[0];
					array_shift($validator);
					if (is_string($fn) && isset($validators[$fn])) {
						if (call_user_func($validators[$fn],$form,
							$element,$validator,&$messages) !== true) return false;
					}
				}					
			}
		}
		return $good;
	}
		
	public function save(&$model,$fields = null) {
		if (!isset($model)) $model = array();
		$this->_f_save_($this,$this,$model,$fields);
		return $this;
	}
	
	public static function _f_save_($form,$parent,&$model,$fields) {
		foreach ($parent->elements as $id => $element) {
			if (isset($element['_f_is_container_']) && $element['_f_is_container_']) {
				_F_EXTENSION_FORM_OBJECT_::_f_save_($form,$element['elements'],&$model,$fields);
			} else if ($fields === null || in_array($id,$fields)) {
				if (isset($element['_f_value_saver_'])) {
					call_user_func($element['_f_value_saver_'],
						$form,$id,$element,$model,$fields);
				} else if (isset($element['value'])) {
					$name = isset($element['field']) ? $element['field'] : $id;
					if (is_array($model)) {
					 	$model[$name] = $element['value'];
					} else {
						$model->$name = $element['value'];
					}
				}
			}
		}
	}

	public function &element($id) {
		if (array_key_exists($id,$this->elements)) {
			return $this->elements[$id];
		}
		foreach ($this->elements as &$element) {
			if (isset($element['_f_is_container_']) && $element['_f_is_container_']) {
				// TODO: container vegiggondolasa...
				$child_element = $element['elements']->element($id);
				if ($child_element !== null) return $child_element;
			}
		}
		$null = null;
		return $null;
	}

	public function value($id,$value = null) {
		$element = $this->element($id);
		if ($element === null) {
			error_log("VerSimF Notice: Undefined element: $id");
			return null;
		}
		if (func_num_args() > 1) {
			$element['value'] = $value;
			return $this;
		}
		return array_key_exists('value',$element) ? $element['value'] : null;
	}

	public function submitted($id = '_f_submit_') {
		return f()->param('_f_form_id_') === $this->id &&
			f()->param('_f_submit_') === $id;
	}

	public function render() {
		f()->render('form.form',array(
			'form' => $this->form,
			'id' => $this->id, 
			'title' => $this->title, 
			'elements' => $this->elements,
			'attr' => array_merge($this->attr,array(
				'id' => $this->id,
				'action' => $this->action,
				'method' => $this->method,
			)),
		));
		return $this;
	}
		
}

